package com.bipbip.controlador;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;

import com.bipbip.beans.DatosLugar;
import com.bipbip.modelo.Lugar;
import com.bipbip.modelo.Publicacion;
import com.bipbip.modelo.Usuario;
import com.bipbip.service.NotificacionesManager;
import com.bipbip.service.ProductoManager;
import com.bipbip.service.PublicacionService;
import com.bipbip.service.UsuarioManager;
import com.bipbip.utils.LugarComparator;

/**
 * Servlet implementation class Controlador
 */
@Controller
@SessionAttributes("usuario")
public class Controlador {

	protected final Log logger = LogFactory.getLog(getClass());

	@Autowired
	private PublicacionService publicacionesService;
	@Autowired
	private NotificacionesManager notificacionesService;
	@Autowired
	private UsuarioManager uManager;
	@Autowired
	private ProductoManager pManager;
	@Autowired
	private Usuario usuarioLoggeado;

	@RequestMapping(value = "/")
	public ModelAndView handleRequestHome(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		return new ModelAndView("home");
	}

	@RequestMapping(value = "/info")
	public ModelAndView handleRequestInfo(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		return new ModelAndView("acercaDe");
	}

	@RequestMapping(value = "/login")
	public ModelAndView login(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		if (usuarioLoggeado != null && usuarioLoggeado.getId() != null) {
			return new ModelAndView("viajes");
		}
		return new ModelAndView("login");
	}

    @RequestMapping(value = "/notificacionesasdfasdf", method = RequestMethod.GET)
    public String getNotificaciones(Model model, Usuario user) {
        model.addAttribute("notificaciones", notificacionesService.getNotificacionesDelUsuario(user));
        return "notificaciones";
    }

	@RequestMapping(value = "/logout")
	public String logout(WebRequest request, SessionStatus status)
			throws ServletException, IOException {
		usuarioLoggeado = null;
		status.setComplete();
		request.removeAttribute("usuario", WebRequest.SCOPE_SESSION);
		return "redirect:home";
	}

	@RequestMapping(value = "/home")
	public ModelAndView dashboard(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		if (usuarioLoggeado != null && usuarioLoggeado.getId() != null) {
			return new ModelAndView("viajes");
		}
		return new ModelAndView("home");
	}

	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public ModelAndView onLoginSubmit(@Valid Usuario usuario,
			BindingResult result, Model model, WebRequest request,
			SessionStatus status) {
		if (result.hasErrors()) {
			return new ModelAndView("login");
		}

		usuarioLoggeado = uManager.getUsuarioByEmailAndPassword(
				usuario.getEmail(), usuario.getPassword());
		if (usuarioLoggeado != null) {
			model.addAttribute("usuario", usuarioLoggeado);
		} else {
			status.setComplete();
			request.removeAttribute("usuario", WebRequest.SCOPE_SESSION);
			model.addAttribute("error", "Email y/o contraseña inválida.");
			return new ModelAndView("login");
		}

		return new ModelAndView("viajes");

	}

	@RequestMapping(value = "/signup", method = RequestMethod.GET)
	public ModelAndView onSignupSubmit(HttpServletRequest request,
			HttpServletResponse response) {
		return new ModelAndView("signup");
	}

	@RequestMapping(value = "/signup", method = RequestMethod.POST)
	public ModelAndView onSignupSubmit(@Valid Usuario usuario,
			BindingResult result, Model model, WebRequest request,
			SessionStatus status) {
		if (result.hasErrors()) {
			usuarioLoggeado = null;
			status.setComplete();
			request.removeAttribute("usuario", WebRequest.SCOPE_SESSION);
			return new ModelAndView("signup");
		}

		try {
			usuarioLoggeado = uManager.registerUsuario(usuario);
			if (usuarioLoggeado != null) {
				model.addAttribute("usuario", usuarioLoggeado);
			} else {
				status.setComplete();
				request.removeAttribute("usuario", WebRequest.SCOPE_SESSION);
				return new ModelAndView("signup");
			}
		} catch (Exception e) {
			usuarioLoggeado = null;
			status.setComplete();
			request.removeAttribute("usuario", WebRequest.SCOPE_SESSION);
			model.addAttribute("error", "El email ya se encuentra registrado.");
			return new ModelAndView("signup");
		}
		return new ModelAndView("viajes");

	}

	@RequestMapping(value = "/search", method = RequestMethod.GET)
	public String buscar(Model model) {
		model.addAttribute("puntoDeBusqueda", new DatosLugar());
		return "busquedaDeViajes";
	}

	@RequestMapping(value = "/search", method = RequestMethod.POST)
	public String procesarBusqueda(Model model, DatosLugar datos) {
		float x = Float.parseFloat(datos.getX());
		float y = Float.parseFloat(datos.getY());

		List<Publicacion> misPubs = publicacionesService.obtenerTodos();
		List<Lugar> lugaresOrdenados = new ArrayList<Lugar>();
		for (Publicacion pub : misPubs) {
			for (Lugar l : pub.getViaje().getLugares()) {
				lugaresOrdenados.add(l);
			}
		}
		Collections.sort(lugaresOrdenados, new LugarComparator(x, y));
		HashSet<Integer> publicaciones = new HashSet<Integer>();
		List<Publicacion> publicacionesOrdenadas = new ArrayList<Publicacion>();
		for (Lugar l : lugaresOrdenados) {
			Publicacion p = l.getViaje().getPublicacion();
			if (!publicaciones.contains(p.getId())) {
				publicacionesOrdenadas.add(p);
				publicaciones.add(p.getId());
			}
		}
		model.addAttribute("misPublicaciones", publicacionesOrdenadas);

		return "misViajes";
	}

}
